// Table.cpp: implementation of the CTable class.
//
//////////////////////////////////////////////////////////////////////


#include "Table.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "iface.h"
#include "Buffer.h"
#include <sys/time.h>

//#include <config.h>

extern	unsigned short	actcode; //from rcinput
extern	unsigned short	realcode; //from rcinput
extern	int				doexit;

#define T_ROWS		2
#define T_COLS		9

static int 	win_counter 	= 0;
int 		    ShowCards 	= 3;
	
typedef enum {
	SL_BLOCK = 0,
	SL_WASTEPILE,
	SL_FOUNDATION1,
	SL_FOUNDATION2,
	SL_FOUNDATION3,
	SL_FOUNDATION4,
	SL_HAND,
	SL_TABLEAU1,
	SL_TABLEAU2,
	SL_TABLEAU3,
	SL_TABLEAU4,
	SL_TABLEAU5,
	SL_TABLEAU6,
	SL_TABLEAU7,
	SL_COUNT } t_slots;
    
CTable::CTable()
{
	int left = 0;
	int top = 0;
	int i;
	
	this->act_slot = SL_BLOCK;
    this->act_row = 0;
	memset( changed, 0xFF, sizeof( changed ) );

	//fill layouts
	
	// 800x600
	layouts[L800X600][SL_BLOCK] = SlotPos( left +19, top, 0, 0 );
	layouts[L800X600][SL_WASTEPILE] = SlotPos( left +95, top, 0, 0 );
	layouts[L800X600][SL_HAND] = SlotPos( left, top + 150, 0, 0 );
	for( i = 0; i < 4; i++ )
	{
		layouts[L800X600][SL_FOUNDATION1+i] = SlotPos( left+(4+i)*80, top, 0, 0 );
	}
	for( i = 0; i < 7; i++ )
	{
		layouts[L800X600][SL_TABLEAU1+i] = SlotPos( left+(1+i)*80, top + 150, 0, 0 );
	}

	
	// 600x800
	layouts[L600X800][SL_BLOCK] = SlotPos( left +19, top, 0, 0 );
	layouts[L600X800][SL_WASTEPILE] = SlotPos( left +95, top, 0, 0 );
	layouts[L600X800][SL_HAND] = SlotPos( left, top + 150, 0, 0 );
	for( i = 0; i < 4; i++ )
	{
		layouts[L600X800][SL_FOUNDATION1+i] = SlotPos( left+(4+i)*80, top, 0, 0 );
	}
	for( i = 0; i < 7; i++ )
	{
		layouts[L600X800][SL_TABLEAU1+i] = SlotPos( left+(1+i)*80, top + 150, 0, 0 );
	}

	layout = L800X600;
	
	Load();
}

CTable::~CTable()
{
	Save();
}

void CTable::Init()
{


	unsigned char i = 0;

	win_counter = 0;

	this->act_slot = SL_BLOCK;
	memset( changed, 0xFF, sizeof( changed ) );

	
	std::cout << inf << "Remove all cards from Block" << std::endl;
	block.RemoveAll();
	std::cout << inf << "Fill the Block" << std::endl;
	block.Fill();

	std::cout << inf << "Shuffle" << std::endl;
	for( i = 0; i < 7; i++ )
		block.Shuffle();

	std::cout << inf << "Shuffle" << std::endl;
	for( i = 0; i < 7; i++ )
		tableau[i].RemoveAll();

	std::cout << inf << "Cleanup Foundations" << std::endl;
	for( i = 0; i < 4; i++ )
		foundation[i].RemoveAll();

	std::cout << inf << "Cleanup Hand" << std::endl;
	hand.RemoveAll();

	std::cout << inf << "Cleanup Wastepile" << std::endl;
	wastepile.RemoveAll();

	unsigned char	filled;

	for( filled = 1; filled < 7; filled++ )
	{
		std::cout << inf << "Poplate tableau " << (int)filled << std::endl;
		for( i = filled; i < 7 ; i++ )
		{
			CCard tmp = block.PopCard();
			tableau[i].PushCard( tmp, true );
		}
	}

	std::cout << inf << "Open all top cards on Tableaus" << std::endl;
	for( i = 0; i < 7 ; i++ )
	{
		CCard tmp = block.PopCard();
		tmp.Flip();
		tableau[i].PushCard( tmp, true );
	}

	act_slot = SL_BLOCK;

	ChangeSelection( true );

}

void CTable::MoveCursor( t_direction _direction)
{
	this->ChangeSelection( false );

	switch( act_slot )
	{
	case SL_BLOCK :
			switch( _direction )
			{
			case DIR_LEFT: act_slot = SL_TABLEAU7; break;
			case DIR_RIGHT: act_slot = SL_WASTEPILE; break;
			case DIR_UP: act_slot = SL_TABLEAU1; break;
			case DIR_DOWN: act_slot = SL_TABLEAU1; break;
			} break;
	case SL_WASTEPILE :
			switch( _direction )
			{
			case DIR_LEFT: act_slot = SL_BLOCK; break;
			case DIR_RIGHT: act_slot = SL_TABLEAU1; break;
			case DIR_UP: act_slot = SL_TABLEAU1; break;
			case DIR_DOWN: act_slot = SL_TABLEAU1; break;
			} break;
	case SL_FOUNDATION1 :
			switch( _direction )
			{
			case DIR_LEFT: act_slot = SL_TABLEAU4; break;
			case DIR_RIGHT: act_slot = SL_TABLEAU5; break;
			case DIR_UP: act_slot = SL_TABLEAU4; break;
			case DIR_DOWN: act_slot = SL_TABLEAU4; break;
			} break;
	case SL_FOUNDATION2 :
			switch( _direction )
			{
			case DIR_LEFT: act_slot = SL_TABLEAU5; break;
			case DIR_RIGHT: act_slot = SL_TABLEAU6; break;
			case DIR_UP: act_slot = SL_TABLEAU5; break;
			case DIR_DOWN: act_slot = SL_TABLEAU5; break;
			} break;
	case SL_FOUNDATION3 :
			switch( _direction )
			{
			case DIR_LEFT: act_slot = SL_TABLEAU6; break;
			case DIR_RIGHT: act_slot = SL_TABLEAU7; break;
			case DIR_UP: act_slot = SL_TABLEAU6; break;
			case DIR_DOWN: act_slot = SL_TABLEAU6; break;
			} break;
	case SL_FOUNDATION4 :
			switch( _direction )
			{
			case DIR_LEFT: act_slot = SL_TABLEAU7; break;
			case DIR_RIGHT: act_slot = SL_BLOCK; break;
			case DIR_UP: act_slot = SL_TABLEAU7; break;
			case DIR_DOWN: act_slot = SL_TABLEAU7; break;
			} break;
	case SL_TABLEAU1 :
			switch( _direction )
			{
			case DIR_LEFT: act_slot = SL_WASTEPILE; break;
			case DIR_RIGHT: act_slot = SL_TABLEAU2; break;
			case DIR_UP: act_slot = SL_WASTEPILE; break;
			case DIR_DOWN: act_slot = SL_WASTEPILE; break;
			} break;
	case SL_TABLEAU2 :
			switch( _direction )
			{
			case DIR_LEFT: act_slot = SL_TABLEAU1; break;
			case DIR_RIGHT: act_slot = SL_TABLEAU3; break;
			case DIR_UP: act_slot = SL_WASTEPILE; break;
			case DIR_DOWN: act_slot = SL_WASTEPILE; break;
			} break;
	case SL_TABLEAU3 :
			switch( _direction )
			{
			case DIR_LEFT: act_slot = SL_TABLEAU2; break;
			case DIR_RIGHT: act_slot = SL_TABLEAU4; break;
			case DIR_UP: act_slot = SL_FOUNDATION1; break;
			case DIR_DOWN: act_slot = SL_FOUNDATION1; break;
			}  break;
	case SL_TABLEAU4 :
			switch( _direction )
			{
			case DIR_LEFT: act_slot = SL_TABLEAU3; break;
			case DIR_RIGHT: act_slot = SL_FOUNDATION1; break;
			case DIR_UP: act_slot = SL_FOUNDATION1; break;
			case DIR_DOWN: act_slot = SL_FOUNDATION1; break;
			}  break;
	case SL_TABLEAU5 :
			switch( _direction )
			{
			case DIR_LEFT: act_slot = SL_FOUNDATION1; break;
			case DIR_RIGHT: act_slot = SL_FOUNDATION2; break;
			case DIR_UP: act_slot = SL_FOUNDATION2; break;
			case DIR_DOWN: act_slot = SL_FOUNDATION2; break;
			}  break;
	case SL_TABLEAU6 :
			switch( _direction )
			{
			case DIR_LEFT: act_slot = SL_FOUNDATION2; break;
			case DIR_RIGHT: act_slot = SL_FOUNDATION3; break;
			case DIR_UP: act_slot = SL_FOUNDATION3; break;
			case DIR_DOWN: act_slot = SL_FOUNDATION3; break;
			}  break;
	case SL_TABLEAU7 :
			switch( _direction )
			{
			case DIR_LEFT: act_slot = SL_FOUNDATION3; break;
			case DIR_RIGHT: act_slot = SL_FOUNDATION4; break;
			case DIR_UP: act_slot = SL_FOUNDATION4; break;
			case DIR_DOWN: act_slot = SL_FOUNDATION4; break;
			}  break;
	}


	this->ChangeSelection( true );
}

void CTable::Save()
{ /*
	FILE* sav = fopen( GAMESDIR "/solitair.sav", "wb" );

	if( sav == NULL ) return;

	fwrite( &ShowCards, 1, sizeof( ShowCards ), sav );

	fwrite( &win_counter, 1, sizeof( win_counter ), sav );

	//Save BLOCK
	unsigned char CardsStored = block.GetCardsStored();

	fwrite( &CardsStored, 1, sizeof( CardsStored ), sav );

	for( unsigned char i = 0; i < CardsStored; i++ )
	{
		CCard card = block.PopCard();
		fwrite( &card, 1, sizeof( card ), sav );
	}

	//save WASTEPILE
	CardsStored = wastepile.GetCardsStored();

	fwrite( &CardsStored, 1, sizeof( CardsStored ), sav );

	for( unsigned char i = 0; i < CardsStored; i++ )
	{
		CCard card = wastepile.PopCard();
		fwrite( &card, 1, sizeof( card ), sav );
	}

	//Save HAND
	int HSource = 0;

	if( &block == hand.GetSource() )
	{
		HSource = SL_BLOCK;
	}
	else
	if( &wastepile == hand.GetSource() )
	{
		HSource = WASTEPILE;
	}
	else
	if( &foundation[0] == hand.GetSource() )
	{
		HSource = FOUNDATION1;
	}
	else
	if( &foundation[1] == hand.GetSource() )
	{
		HSource = FOUNDATION2;
	}
	else
	if( &foundation[2] == hand.GetSource() )
	{
		HSource = FOUNDATION3;
	}
	else
	if( &foundation[3] == hand.GetSource() )
	{
		HSource = FOUNDATION4;
	}
	else
	if( &tableau[0] == hand.GetSource() )
	{
		HSource = TABLEAU1;
	}
	else
	if( &tableau[1] == hand.GetSource() )
	{
		HSource = TABLEAU2;
	}
	else
	if( &tableau[2] == hand.GetSource() )
	{
		HSource = TABLEAU3;
	}
	else
	if( &tableau[3] == hand.GetSource() )
	{
		HSource = TABLEAU4;
	}
	else
	if( &tableau[4] == hand.GetSource() )
	{
		HSource = TABLEAU5;
	}
	else
	if( &tableau[5] == hand.GetSource() )
	{
		HSource = TABLEAU6;
	}
	else
	if( &tableau[6] == hand.GetSource() )
	{
		HSource = TABLEAU7;
	}

	fwrite( &HSource, 1, sizeof( HSource ), sav );

	CardsStored = hand.GetCardsStored();

	fwrite( &CardsStored, 1, sizeof( CardsStored ), sav );

	for( unsigned char i = 0; i < CardsStored; i++ )
	{
		CCard card = hand.PopCard();
		fwrite( &card, 1, sizeof( card ), sav );
	}

	//Save Tableaus
	for( int j = 0; j < 7; j++ )
	{
		CardsStored = tableau[j].GetCardsStored();

		fwrite( &CardsStored, 1, sizeof( CardsStored ), sav );

		for( unsigned char i = 0; i < CardsStored; i++ )
		{
			CCard card = tableau[j].PopCard();
			fwrite( &card, 1, sizeof( card ), sav );
		}
	}

	//Save Foundations
	for( int j = 0; j < 4; j++ )
	{
		CardsStored = foundation[j].GetCardsStored();

		fwrite( &CardsStored, 1, sizeof( CardsStored ), sav );

		for( unsigned char i = 0; i < CardsStored; i++ )
		{
			CCard card = foundation[j].PopCard();
			fwrite( &card, 1, sizeof( card ), sav );
		}
	}

	fclose( sav );
*/
}

void CTable::Load()
{
/*
	int SavShowCards = 0;

	FILE* sav = fopen( GAMESDIR "/solitair.sav", "rb" );

	if( sav == NULL ) return;

	fread( &SavShowCards, 1, sizeof( SavShowCards ), sav );

	if( ( SavShowCards != 3 ) && ( SavShowCards != 1 ) )
	{
		return;
	}

	ShowCards = SavShowCards;

	fread( &win_counter, 1, sizeof( win_counter ), sav );

	CCard card;
	unsigned char CardsStored;
	CBuffer buffer;


//Restore BLOCK

	block.RemoveAll();

	fread( &CardsStored, 1, sizeof( CardsStored ), sav );

	buffer.RemoveAll();
	for( unsigned char i = 0; i < CardsStored; i++ )
	{
		fread( &card, 1, sizeof( card ), sav );
		buffer.PushCard( card, true );
	}

	for( unsigned char i = 0; i < CardsStored; i++ )
	{
		block.PushCard( buffer.PopCard(), true );
	}

//Restore Wastepile
	fread( &CardsStored, 1, sizeof( CardsStored ), sav );

	buffer.RemoveAll();
	for( unsigned char i = 0; i < CardsStored; i++ )
	{
		fread( &card, 1, sizeof( card ), sav );
		buffer.PushCard( card, true );
	}

	for( unsigned char i = 0; i < CardsStored; i++ )
	{
		wastepile.PushCard( buffer.PopCard(), true );
	}
//Restore HAND
	int HSource;
	fread( &HSource, 1, sizeof( HSource ), sav );

	switch( HSource )
	{
		case 0:
			hand.SetSource(NULL);
			break;
		case SL_BLOCK:
			hand.SetSource(&block);
			break;
		case SL_WASTEPILE:
			hand.SetSource(&wastepile);
			break;
		case SL_FOUNDATION1:
			hand.SetSource(&foundation[0]);
			break;
		case SL_FOUNDATION2:
			hand.SetSource(&foundation[1]);
			break;
		case SL_FOUNDATION3:
			hand.SetSource(&foundation[2]);
			break;
		case SL_FOUNDATION4:
			hand.SetSource(&foundation[3]);
			break;
		case SL_TABLEAU1:
			hand.SetSource(&tableau[0]);
			break;
		case SL_TABLEAU2:
			hand.SetSource(&tableau[1]);
			break;
		case SL_TABLEAU3:
			hand.SetSource(&tableau[2]);
			break;
		case SL_TABLEAU4:
			hand.SetSource(&tableau[3]);
			break;
		case SL_TABLEAU5:
			hand.SetSource(&tableau[4]);
			break;
		case SL_TABLEAU6:
			hand.SetSource(&tableau[5]);
			break;
		case SL_TABLEAU7:
			hand.SetSource(&tableau[6]);
			break;
	}


	fread( &CardsStored, 1, sizeof( CardsStored ), sav );

	buffer.RemoveAll();
	for( unsigned char i = 0; i < CardsStored; i++ )
	{
		fread( &card, 1, sizeof( card ), sav );
		buffer.PushCard( card, true );
	}

	for( unsigned char i = 0; i < CardsStored; i++ )
	{
		hand.PushCard( buffer.PopCard(), true );
	}

//Restore Tableaus
	for( int j = 0; j < 7; j++ )
	{
		fread( &CardsStored, 1, sizeof( CardsStored ), sav );

		buffer.RemoveAll();
		for( unsigned char i = 0; i < CardsStored; i++ )
		{
			fread( &card, 1, sizeof( card ), sav );
			buffer.PushCard( card, true );
		}

		for( unsigned char i = 0; i < CardsStored; i++ )
		{
			tableau[j].PushCard( buffer.PopCard(), true );
		}
	}
//Restore Foundations
	for( int j = 0; j < 4; j++ )
	{
		fread( &CardsStored, 1, sizeof( CardsStored ), sav );

		buffer.RemoveAll();
		for( unsigned char i = 0; i < CardsStored; i++ )
		{
			fread( &card, 1, sizeof( card ), sav );
			buffer.PushCard( card, true );
		}

		for( unsigned char i = 0; i < CardsStored; i++ )
		{
			foundation[j].PushCard( buffer.PopCard(), true );
		}
	}


	fclose( sav );
*/
}

/*
int CTable::Run()
{

//	BBSetBackground( BACK_C );

//	FBCopyImage( 0, 0, WIDTH, HEIGHT, BBGetData() );

//	FBDrawString( 300, 255, 42, "Loading...", 250, 0 );

	//Outer loop for initialization
	while( 0 == doexit )
	{

//		this->Init();

		this->Display();

		//Inner loop for game controlling
		while( 0 == doexit )
		{
			//Handle keys
			this->HandleKeysPressed();

			if( 0 != doexit ) break;

			//Display changes
		}
	}

	return 0;
}
*/
void CTable::ShowHelp()
{
/*
	const int Hx = 100;
	const int Hy = 100;
	const int Hwidth = 520;
	const int Hheight = 376;

	FBFillRect( Hx+8, Hy+8, Hwidth, Hheight, Convert_24_8( 0,0,0) );
	FBFillRect( Hx, Hy, Hwidth, Hheight, 19 );

	FBDrawHLine( Hx + 5, Hy + 55, 400, Convert_24_8( 255,255,255) );
	FBDrawHLine( Hx + 5, Hy + 56, 400, Convert_24_8( 255,255,255) );

	FBDrawString( Hx + 5, Hy + 5, 48, "Solitair for D-BOX", Convert_24_8( 255,255,255), 0 );

	FBDrawString( Hx + 5, Hy + 60, 32, "TheMoon, 2003", Convert_24_8( 255,255,255), 0 );

	FBDrawString( Hx + 5, Hy + 102, 32, "Key mappings:", Convert_24_8( 255,255,255), 0 );

	FBDrawString( Hx + 5, Hy + 135, 32, "(Red)", Convert_24_8( 255,255,255), 0 );
	FBDrawString( Hx + 105, Hy + 135, 32, "- Restart game", Convert_24_8( 255,255,255), 0 );
	FBDrawString( Hx + 5, Hy + 168, 32, "(Blue)", Convert_24_8( 255,255,255), 0 );
	FBDrawString( Hx + 105, Hy + 168, 32, "- Wizard", Convert_24_8( 255,255,255), 0 );
	FBDrawString( Hx + 5, Hy + 201, 32, "(?)", Convert_24_8( 255,255,255), 0 );
	FBDrawString( Hx + 105, Hy + 201, 32, "- Help screen", Convert_24_8( 255,255,255), 0 );
	FBDrawString( Hx + 5, Hy + 234, 32, "(Home)", Convert_24_8( 255,255,255), 0 );
	FBDrawString( Hx + 105, Hy + 234, 32, "- Exit", Convert_24_8( 255,255,255), 0 );
	FBDrawString( Hx + 5, Hy + 267, 32, "(1 - 7)", Convert_24_8( 255,255,255), 0 );
	FBDrawString( Hx + 105, Hy + 267, 32, "- Tableau", Convert_24_8( 255,255,255), 0 );
	FBDrawString( Hx + 5, Hy + 300, 32, "(-) (+)", Convert_24_8( 255,255,255), 0 );
	FBDrawString( Hx + 105, Hy + 300, 32, "- Change selection", Convert_24_8( 255,255,255), 0 );
	FBDrawString( Hx + 5, Hy + 333, 32, "DBOX", Convert_24_8( 255,255,255), 0 );
	FBDrawString( Hx + 105, Hy + 333, 32, "- Setup menu", Convert_24_8( 255,255,255), 0 );
*/


}

bool CTable::Relayout()
{
	// check width and height and relocate Slots accordently
	
	int scrwidth 	= this->ScreenWidth();
	int scrheight 	= this->ScreenHeight();
	int orient      = this->GetOrientation();
	
	std::cout << inf << "CTable::Relayout:" << "\n" 
		<< "\t" << "screen width: " << scrwidth << "\n"
		<< "\t" << "screen height: " << scrheight << "\n"
		<< "\t" << "screen orientation: " << orient << "\n"
	<< std::endl;	

	if( scrwidth == 600 )
		layout = L600X800;
	else
		layout = L800X600;
		
	Display(true);
	
	return true;
}

bool CTable::Setup()
{
	bool ret = true;
	if( ret )
		ret = this->Relayout();
	return true;
}

void CTable::Handle(t_doing _doing)
{
	static bool	HelpOnScreen = false;
//	static bool	MenuOnScreen = false;

	if( true == HelpOnScreen )
	{
//		FBCopyImage( 0, 0, WIDTH, HEIGHT, BBGetData() );
		HelpOnScreen = false;
		return;
	}

	switch( _doing )
	{
 		case DO_SEL_0 :

			ChangeSelection( false );
			changed[ act_slot ] = true;
			changed[ SL_BLOCK ] = true;
			act_slot = SL_BLOCK;
			ChangeSelection( );


			break;
		case DO_SEL_1 :

			ChangeSelection( false );
			changed[ act_slot ] = true;
			changed[ SL_TABLEAU1 ] = true;
			act_slot = SL_TABLEAU1;
			ChangeSelection( true, false );

			break;
		case DO_SEL_2 :
			ChangeSelection( false );
			changed[ act_slot ] = true;
			changed[ SL_TABLEAU2 ] = true;
			act_slot = SL_TABLEAU2;
			ChangeSelection( true, false );

			break;
		case DO_SEL_3 :
			ChangeSelection( false );
			changed[ act_slot ] = true;
			changed[ SL_TABLEAU3 ] = true;
			act_slot = SL_TABLEAU3;
			ChangeSelection( true, false );

			break;
		case DO_SEL_4 :
			ChangeSelection( false );
			changed[ act_slot ] = true;
			changed[ SL_TABLEAU4 ] = true;
			act_slot = SL_TABLEAU4;
			ChangeSelection( true, false );

			break;
		case DO_SEL_5 :
			ChangeSelection( false );
			changed[ act_slot ] = true;
			changed[ SL_TABLEAU5 ] = true;
			act_slot = SL_TABLEAU5;
			ChangeSelection( true, false );

			break;
		case DO_SEL_6 :
			ChangeSelection( false );
			changed[ act_slot ] = true;
			changed[ SL_TABLEAU6 ] = true;
			act_slot = SL_TABLEAU6;
			ChangeSelection( true, false );

			break;
		case DO_SEL_7 :
			ChangeSelection( false );
			changed[ act_slot ] = true;
			changed[ SL_TABLEAU7 ] = true;
			act_slot = SL_TABLEAU7;
			ChangeSelection( true, false );

			break;
		case DO_SEL_8 :

			break;
		case DO_SEL_9 :

			break;

		case DO_MOVERIGHT :
			this->MoveCursor( DIR_RIGHT );
			break;
		case DO_MOVELEFT :
			this->MoveCursor( DIR_LEFT );
			break;
		case DO_MOVEUP :
			this->MoveCursor( DIR_UP );
			break;
		case DO_MOVEDOWN :
			this->MoveCursor( DIR_DOWN );
			break;
		case DO_ACTION :
			this->DoAction();
			break;
		case DO_INIT	 :
			this->Init();
			break;
		case DO_WIZARD :
			Wizard();
			break;
		case DO_SELPLUS :
			changed[ act_slot ] = true;
			ChangeSelection( true, false );
			break;
		case DO_SELMINUS :
			changed[ act_slot ] = true;
			ChangeSelection( false, false );
			break;
		case DO_HELP :

			this->ShowHelp();
			HelpOnScreen = true;

			break;
		case DO_RELAYOUT :
			this->Relayout();
			Display( true );
			break;
		case DO_SETUP :
			if( this->Setup() )
				this->Init();
			//FBCopyImage( 0, 0, WIDTH, HEIGHT, BBGetData() );
			Display( true );
			break;

		default:
			return;

			break;
	}

	Display();
		

}


#define TOP	25
#define LEFT	25

void CTable::Display( bool _full_update )
{

	bool some_changes = _full_update;
	
	if( _full_update )
	{
		memset( changed, 1, sizeof( changed ) );
		CIface::ClearScreen();
	}
	std::cout << inf << "CTable::Display("<< _full_update << ")" << std::endl;
	
	if( changed[ SL_BLOCK ] )
	{
//
		some_changes = true;
		block.Draw( LEFT + 15, TOP, SL_BLOCK == act_slot );
	}

	if( changed[ SL_WASTEPILE ] )
	{
		wastepile.Draw( LEFT + 95, TOP, SL_WASTEPILE == act_slot );
		some_changes = true;
	}

	int i;

	for( i = 0; i < 4; i++ )
	{
		if( changed[ SL_FOUNDATION1 + i ] )
		{
			foundation[i].Draw( LEFT+(4+i)*80, TOP, (SL_FOUNDATION1 + i) == act_slot );
			some_changes = true;
		}
	}

	if( changed[ SL_HAND ] )
	{
		hand.Draw( LEFT, TOP + 150 );
		some_changes = true;
	}

	for( i = 0; i < 7; i++ )
	{
		if( changed[ SL_TABLEAU1 + i ] )
		{
			tableau[i].Draw( LEFT+(1+i)*80, TOP + 150, (SL_TABLEAU1 + i) == act_slot );
			some_changes = true;
		}
	}

	memset( changed, 0, sizeof( changed ) );

	if( _full_update )
	{
		CIface::DrawText( "Solitaire", 30, 1 );
		CIface::FullUpdate();
	}
	else
	{
		CIface::UpdateAreas();
	}
}

//automaticly select all possible cards or deselect all cards
void CTable::ChangeSelection(bool select, bool select_all )
{

	CSlot* sel_slot = NULL;

	changed[ act_slot ] = true;

	switch( act_slot )
	{
	case SL_BLOCK :		sel_slot = &block;		break;
	case SL_WASTEPILE :	sel_slot = &wastepile;		break;
	case SL_FOUNDATION1 :
	case SL_FOUNDATION2 :
	case SL_FOUNDATION3 :
	case SL_FOUNDATION4 :  sel_slot = &foundation[act_slot - SL_FOUNDATION1];	break;
	case SL_TABLEAU1 :
	case SL_TABLEAU2 :
	case SL_TABLEAU3 :
	case SL_TABLEAU4 :
	case SL_TABLEAU5 :
	case SL_TABLEAU6 :
	case SL_TABLEAU7 :		sel_slot = &tableau[act_slot - SL_TABLEAU1]; break;
	}

	if( sel_slot )
	{
		if( select_all )
		{
			if( select )
				while( sel_slot->IncreaseSelection() );
			else
				while( sel_slot->DecreaseSelection() );
		}
		else
		{
			if( select )
				sel_slot->IncreaseSelection();
			else
				sel_slot->DecreaseSelection();
		}
	}
}

void CTable::DoAction()
{

	CBuffer buffer;
//	CCard	tmp;

	CSlot* fnd = NULL;
	CSlot* tab = NULL;

	switch( act_slot )
	{
	case SL_BLOCK :
		/* move 3 cards to wastepile */

		//check IncreaseSelection and DecreaseSelection
		//regarding increaseSelection (all) or (+1)

		if( 0 != hand.GetCardsStored() ) return;

		buffer.RemoveAll();

		if( block.GetCardsStored() != 0 )
		{
			CCard tmp(block.PopCard()) ;
			tmp.Flip();
			wastepile.PushCard( tmp );

			if( 3 == ShowCards )
			{
				tmp = block.PopCard();
				tmp.Flip();
				wastepile.PushCard( tmp );

				tmp = block.PopCard();
				tmp.Flip();
				wastepile.PushCard( tmp );
			}

			act_slot = SL_WASTEPILE;

		}
		else
		{
			if( wastepile.GetCardsStored() )
			{
				CCard tmp(wastepile.PopCard());

				while( tmp.IsValid() )
				{
					tmp.Flip();
					block.PushCard( tmp, true );
					tmp = wastepile.PopCard();
				}

			}
		}
		changed[ SL_WASTEPILE ] = true;
		changed[ SL_BLOCK ] = true;

		ChangeSelection( );

		return;

	case SL_WASTEPILE :
		/* put one card to hand */
		/* or put back from the hand */

		if( hand.GetCardsStored() )
		{
			if( hand.GetSource() == &wastepile )
			{
				CCard tmp(hand.PopCard());
				wastepile.PushCard( tmp, true );

				hand.SetSource( NULL );
			}

		}
		else
		{
			CCard tmp(wastepile.PopCard());
			if( false == tmp.IsValid() ) break;

			if( false == hand.PushCard( tmp ) )
			{
				wastepile.PushCard( tmp, true );
			}

			hand.SetSource( &wastepile );
		}

		changed[ SL_WASTEPILE ] = true;
		changed[ SL_HAND ] = true;

		return;

	case SL_FOUNDATION1 :
	case SL_FOUNDATION2 :
	case SL_FOUNDATION3 :
	case SL_FOUNDATION4 :  fnd = &foundation[act_slot - SL_FOUNDATION1];	break;
	case SL_TABLEAU1 :
	case SL_TABLEAU2 :
	case SL_TABLEAU3 :
	case SL_TABLEAU4 :
	case SL_TABLEAU5 :
	case SL_TABLEAU6 :
	case SL_TABLEAU7 :		tab = &tableau[act_slot - SL_TABLEAU1]; break;
	}

	if( fnd )
	{
		if( 0 == hand.GetCardsStored() )
		{

			CCard tmp(fnd->PopCard());

			if( false == tmp.IsValid() ) return;

			hand.PushCard( tmp );

			hand.SetSource( fnd );
			changed[ act_slot ] = true;
			changed[ SL_HAND ] = true;

			CheckWin( false );

			ChangeSelection( );

			return;
		}
		else
		{
			if( fnd == hand.GetSource() )
			{
				CCard tmp(hand.PopCard());

				fnd->PushCard( tmp, true );

				changed[ act_slot ] = true;
				changed[ SL_HAND ] = true;

				CheckWin( true );

				ChangeSelection( );

				return;
			}
			else
			{
				CCard tmp(hand.PeekCard());


				if( false == fnd->PushCard( tmp ) ) return;

				hand.RemoveAll();

				changed[SL_HAND] = true;
				changed[act_slot] = true;

				CheckWin( true );


				ChangeSelection();

				return;
			}
		}

	}

	if( tab )
	{
		if( 0 == hand.GetCardsStored() )
		{
			CCard tmp( tab->PeekCard() );

			if( tmp.IsValid() && tmp.IsFaceDown() )
			{
				tmp = tab->PopCard();
				tmp.Flip();
				tab->PushCard( tmp, true );
				changed[ act_slot ] = true;
				ChangeSelection();
				return;
			}

			tab->GetSelectedCards( &buffer );

			tmp = buffer.PopCard();

			while( tmp.IsValid() )
			{
				hand.PushCard( tmp );
				tmp = buffer.PopCard();
			}

			hand.SetSource( tab );
			changed[ act_slot ] = true;
			changed[ SL_HAND ] = true;

			ChangeSelection( );

			return;
		}
		else
		{

			if( tab == hand.GetSource() )
			{


				hand.PeekAllCards( &buffer );

				hand.RemoveAll();


				CCard tmp(buffer.PopCard());

				while( tmp.IsValid() )
				{

					tab->PushCard( tmp, true );

					tmp = buffer.PopCard();
				}
				changed[ act_slot ] = true;
				changed[ SL_HAND ] = true;


				ChangeSelection( );


				return;
			}
			else
			{


				hand.PeekAllCards( &buffer );


				CCard tmp(buffer.PopCard());


				if( false == tab->PushCard( tmp ) ) return;


				tmp = buffer.PopCard();

				while( tmp.IsValid() )
				{

					tab->PushCard( tmp );

					tmp = buffer.PopCard();
				}


				hand.RemoveAll();

				changed[SL_HAND] = true;
				changed[act_slot] = true;

				ChangeSelection();

				return;
			}
		}
	}

}

/* takes top card from the slot and movies it (if possible) to the foundation */
void CTable::Wizard()
{

	CBuffer buffer;
	CSlot* slot = NULL;

	if( hand.GetCardsStored() ) return;


	unsigned char prev_slot = act_slot;

	switch( act_slot )
	{
	case SL_BLOCK : this->DoAction(); break;
	case SL_WASTEPILE : slot = &wastepile;	break;
	case SL_FOUNDATION1 :  slot = &foundation[0]; break;
	case SL_FOUNDATION2 :  slot = &foundation[1]; break;
	case SL_FOUNDATION3 :  slot = &foundation[2]; break;
	case SL_FOUNDATION4 :  slot = &foundation[3]; break;
	case SL_TABLEAU1 :	slot = &tableau[0]; break;
	case SL_TABLEAU2 :	slot = &tableau[1]; break;
	case SL_TABLEAU3 :	slot = &tableau[2]; break;
	case SL_TABLEAU4 :	slot = &tableau[3]; break;
	case SL_TABLEAU5 :	slot = &tableau[4]; break;
	case SL_TABLEAU6 :	slot = &tableau[5]; break;
	case SL_TABLEAU7 :	slot = &tableau[6]; break;
	}

	if( slot )
	{
		CCard tmp(slot->PeekCard());

		if( false == tmp.IsValid() ) return;

		for( unsigned char i = 0; i < 4; i++ )
		{
			if( foundation[i].PushCard( tmp ) )
			{
				changed[ SL_FOUNDATION1 + i ] = true;
				changed[ prev_slot ] = true;

				slot->PopCard();

				CheckWin( true );

				return;
			}
		}
	}
}


void CTable::CheckWin( bool _add )
{

	if( _add )
		win_counter++;
	else
		win_counter--;



	if( win_counter == 52 )
	{
		this->Init();
	}
}

